// Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.

// fleet服务方法
package fleet

import (
	"fleetmanager/api/errors"
	"fleetmanager/api/model/fleet"
	"fleetmanager/api/params"
	"fleetmanager/api/service/constants"
	"fleetmanager/client"
	"fleetmanager/db/dao"
	"fleetmanager/logger"

	"github.com/beego/beego/v2/server/web/context"
	EipModel "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v2/model"
	EipModelV3 "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/eip/v3/model"
)

type EipService struct {
	ctx    *context.Context
	logger *logger.FMLogger
}

func NewEipService(ctx *context.Context, logger *logger.FMLogger) *EipService {
	s := &EipService{
		ctx:    ctx,
		logger: logger,
	}
	return s
}

func (s *EipService) ListIpPools() (*fleet.ListIpPoolsResp, *errors.CodedError) {
	projectId := s.ctx.Input.Param(params.ProjectId)
	region := s.ctx.Input.Query(params.QueryRegion)
	ipPools := &fleet.ListIpPoolsResp{
		Count:         0,
		PublicIpPools: []fleet.PublicIpPool{},
		CommonPools:   []fleet.CommonPool{},
	}
	if region == "" {
		return nil, errors.NewErrorF(errors.InvalidParameterValue, "region required")
	}
	u, err := dao.GetUserResConfByOriProjectId(projectId)
	if err != nil {
		return nil, errors.NewErrorF(errors.ServerInternalError, err.Error())
	}
	eipV3Client := client.GetEipV3Client(u.AccessKey, u.SecretAccessKey, region, u.ProjectId)
	PublicIpPoolsListfromV3, errC := client.ListPublicIpPoolsByStatus(eipV3Client, constants.PublicPoolStatusActive)
	if errC != nil {
		s.logger.Error("list public ip pools from eip v3 client error: %+v", errC)
		return nil, errors.NewErrorF(errors.ServerInternalError, "list public ip pools from eip v3 client error")
	}
	for _, publicIpPool := range *PublicIpPoolsListfromV3.PublicipPools {
		ipPools.PublicIpPools = append(ipPools.PublicIpPools, *s.BuildPublicIpPool(&publicIpPool))
	}

	CommonIpPoolsFromV3, errC := client.ListPublicIpCommonPools(eipV3Client)
	if errC != nil {
		s.logger.Error("list common public ip pools from eip v3 client error: %+v", errC)
		return nil, errors.NewErrorF(errors.ServerInternalError, "list common public ip pools from eip v3 client error")
	}
	for _, commonPool := range *CommonIpPoolsFromV3.CommonPools {
		ipPools.CommonPools = append(ipPools.CommonPools, *s.BuildCommonIpPool(&commonPool))
	}
	ipPools.Count = len(ipPools.PublicIpPools) + len(ipPools.CommonPools)
	return ipPools, nil
}

func (s *EipService) ListBandwidths() (*fleet.ListBandWidthsResp, *errors.CodedError) {
	projectId := s.ctx.Input.Param(params.ProjectId)
	region := s.ctx.Input.Query(params.QueryRegion)
	Bandwidths := &fleet.ListBandWidthsResp{
		Count:      0,
		Bandwidths: []fleet.BandwidthInfo{},
	}
	if region == "" {
		return nil, errors.NewErrorF(errors.InvalidParameterValue, "region required")
	}
	u, err := dao.GetUserResConfByOriProjectId(projectId)
	if err != nil {
		return nil, errors.NewErrorF(errors.ServerInternalError, err.Error())
	}
	eipClient := client.GetEipClient(u.AccessKey, u.SecretAccessKey, region, u.ProjectId)
	shareType, errC := s.GetBandwidthShareType()
	if errC != nil {
		return nil, errors.NewErrorF(errors.ServerInternalError, errC.Error())
	}
	bandwidthList, errD := client.ListBandwidthsByShareType(eipClient, shareType)
	if errD != nil {
		s.logger.Error("list bandwidth from eip client error: %+v", errD)
		return nil, errors.NewErrorF(errors.ServerInternalError, "list eip type from eip client error")
	}
	for _, bandwidth := range *bandwidthList.Bandwidths {
		Bandwidths.Bandwidths = append(Bandwidths.Bandwidths, *s.BuildBandwidth(&bandwidth))
	}
	Bandwidths.Count = len(Bandwidths.Bandwidths)
	return Bandwidths, nil
}

func (s *EipService) BuildPublicIpPool(publicPool *EipModelV3.PublicipPoolShowResp) *fleet.PublicIpPool {
	return &fleet.PublicIpPool{
		Id:        *publicPool.Id,
		Name:      *publicPool.Name,
		Status:    *publicPool.Status,
		Size:      int(*publicPool.Size),
		Used:      int(*publicPool.Used),
		CreatedAt: *publicPool.CreatedAt,
	}
}

func (s *EipService) BuildCommonIpPool(commonIpPool *EipModelV3.CommonPoolDict) *fleet.CommonPool {
	return &fleet.CommonPool{
		Name:   *commonIpPool.Name,
		Status: *commonIpPool.Status,
		Type:   *commonIpPool.Type,
		Used:   int(*commonIpPool.Used),
	}
}

func (s *EipService) BuildBandwidth(bandwidth *EipModel.BandwidthResp) *fleet.BandwidthInfo {
	return &fleet.BandwidthInfo{
		Id:            *bandwidth.Id,
		Name:          *bandwidth.Name,
		BandwidthType: *bandwidth.BandwidthType,
		ShareType:     *bandwidth.ShareType,
		ChargeMode:    *bandwidth.ChargeMode,
		Size:          int(*bandwidth.Size),
		Status:        *bandwidth.Status,
		CreatedAt:     *bandwidth.CreatedAt,
	}
}

func (s *EipService) GetBandwidthShareType() (EipModel.ListBandwidthsRequestShareType, *errors.CodedError) {
	shareType := s.ctx.Input.Query(params.QueryShareType)
	switch shareType {
	case constants.BandwidthShareTypeWhole:
		return EipModel.GetListBandwidthsRequestShareTypeEnum().WHOLE, nil
	case constants.BandwidthShareTypePre:
		return EipModel.GetListBandwidthsRequestShareTypeEnum().PER, nil
	default:
		return EipModel.GetListBandwidthsRequestShareTypeEnum().WHOLE, nil
	}
}
